<?php
namespace App\Http\Model;

use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Redis;

/**
 * 用户黑名单
 */
class UserBlacklist extends Base
{
    protected $table = 'user_blacklist';
    protected $blackWordTable = 'black_word';
    protected $blackWordLogTable = 'black_word_log';

    //黑名单用户ID缓存
    public $userBlackKey = 'USERBLACK:USER:';//string USERBLACK:USER:{user_id} => {string}

    //用户黑名单计数器私聊
    public $userBlackCounterSmsKey = 'USERBLACK:COUNTER:SMS:';//set USERBLACK:COUNTER:SMS:{user_id}:{Ymd/YmdH/YmdHi}:{toUserType:1=用户2=主播} => {toUserId}

    //用户黑名单计数器搜索
    public $userBlackCounterSearchKey = 'USERBLACK:COUNTER:SEARCH:';//hash USERBLACK:COUNTER:SEARCH:{user_id}:{Ymd/YmdH/YmdHi} => {keyword}

    //用户黑名单计数器举报
    public $userBlackCounterReportKey = 'USERBLACK:COUNTER:REPORT:';//set USERBLACK:COUNTER:REPORT:{user_id}:{YmdH} => {fromUserId}

    //用户黑名单计数器语言
    public $userBlackCounterWordKey = 'USERBLACK:COUNTER:WORD:';//set USERBLACK:COUNTER:WORD:{user_id}:{YmdH} => {fromUserId}

    //黑名单语言缓存
    public $blackWordAllKey = 'BLACKWORD:ALL:';//string BLACKWORD:ALL:{立即封禁 1=否 2=是} => {string}

    public function __construct(array $attributes = [])
    {
        parent::__construct($this->table, $attributes);
    }

    /**
     * 设置用户黑名单计数器私聊
     */
    public function setUserBlackCounterSms($userId, $toUserId, $toUserType){
        $time = time();
        //1天之内
        $cacheKey = $this->userBlackCounterSmsKey.$userId.':'.date('Ymd', $time).':'.$toUserType;
        Redis::SADD($cacheKey, $toUserId);
        Redis::expire($cacheKey, 2*86400);
        //5分钟之内私聊
        $cacheKey = $this->userBlackCounterSmsKey.$userId.':'.date('YmdH', $time).':'.$toUserType;
        Redis::SADD($cacheKey, $toUserId);
        Redis::expire($cacheKey, 300);
        //1分钟之内
        $cacheKey = $this->userBlackCounterSmsKey.$userId.':'.date('YmdHi', $time).':'.$toUserType;
        Redis::SADD($cacheKey, $toUserId);
        Redis::expire($cacheKey, 300);
    }

    /**
     * 设置用户黑名单计数器举报
     */
    public function setUserBlackCounterReport($fromUserId, $toUserId){
        $time = time();
        //小时
        $cacheKey = $this->userBlackCounterReportKey.$toUserId.':'.date('YmdH', $time);
        Redis::SADD($cacheKey, $fromUserId);
        Redis::expire($cacheKey, 10*86400);
    }

    /**
     * 设置用户黑名单计数器搜索
     */
    public function setUserBlackCounterSearch($userId, $keyword){
        $time = time();
        $ymd = date("Y-m-d H:i:s");
        //1天之内
        $cacheKey = $this->userBlackCounterSearchKey.$userId.':'.date('Ymd', $time);
        Redis::hset($cacheKey, $ymd, $keyword);
        Redis::expire($cacheKey, 2*86400);
        //1分钟之内
        $cacheKey = $this->userBlackCounterSearchKey.$userId.':'.date('YmdHi', $time);
        Redis::hset($cacheKey, $ymd, $keyword);
        Redis::expire($cacheKey, 300);
    }

    /**
     * 设置用户黑名单计数器语言
     */
    public function setUserBlackCounterWord($userId, $logId){
        $time = time();
        //小时
        $cacheKey = $this->userBlackCounterWordKey.$userId.':'.date('YmdH', $time);
        Redis::SADD($cacheKey, $logId);
        Redis::expire($cacheKey, 10*86400);
    }

    /**
     * 用户校验是否需要加入黑名单
     */
    public function userToBlack($userId, $blackConfig){
        $time = time();

        $log = [];
        do {
            //1天之内私聊
            if(!empty($blackConfig['1_day_sms_num'])) {
                $cacheKey = $this->userBlackCounterSmsKey.$userId.':'.date('Ymd', $time).':1';
                $num = Redis::SCARD($cacheKey);
                if($num > $blackConfig['1_day_sms_num']) {
                    $log['type'] = 1;
                    $log['desc'] = '1天之内超过'.$blackConfig['1_day_sms_num'].'个用户';
                    break;
                }
                $cacheKey = $this->userBlackCounterSmsKey.$userId.':'.date('Ymd', $time).':2';
                $num = Redis::SCARD($cacheKey);
                if($num > $blackConfig['1_day_sms_num']) {
                    $log['type'] = 2;
                    $log['desc'] = '1天之内超过'.$blackConfig['1_day_sms_num'].'个主播';
                    break;
                }
            }
            //5分钟之内私聊
            if(!empty($blackConfig['5_minute_sms_num'])) {
                $cacheKey = $this->userBlackCounterSmsKey.$userId.':'.date('YmdH', $time).':1';
                $num = Redis::SCARD($cacheKey);
                if($num > $blackConfig['5_minute_sms_num']) {
                    $log['type'] = 3;
                    $log['desc'] = '5分钟之内超过'.$blackConfig['5_minute_sms_num'].'个用户';
                    break;
                }
                $cacheKey = $this->userBlackCounterSmsKey.$userId.':'.date('YmdH', $time).':2';
                $num = Redis::SCARD($cacheKey);
                if($num > $blackConfig['5_minute_sms_num']) {
                    $log['type'] = 4;
                    $log['desc'] = '5分钟之内超过'.$blackConfig['5_minute_sms_num'].'个主播';
                    break;
                }
            }
            //1分钟之内私聊
            if(!empty($blackConfig['1_minute_sms_num'])) {
                $cacheKey = $this->userBlackCounterSmsKey.$userId.':'.date('YmdHi', $time).':1';
                $num = Redis::SCARD($cacheKey);
                if($num > $blackConfig['1_minute_sms_num']) {
                    $log['type'] = 5;
                    $log['desc'] = '1分钟之内超过'.$blackConfig['1_minute_sms_num'].'个用户';
                    break;
                }
                $cacheKey = $this->userBlackCounterSmsKey.$userId.':'.date('YmdHi', $time).':2';
                $num = Redis::SCARD($cacheKey);
                if($num > $blackConfig['1_minute_sms_num']) {
                    $log['type'] = 6;
                    $log['desc'] = '1分钟之内超过'.$blackConfig['1_minute_sms_num'].'个主播';
                    break;
                }
            }

            //1天之内搜索
            if(!empty($blackConfig['1_day_search_num'])) {
                $cacheKey = $this->userBlackCounterSearchKey.$userId.':'.date('Ymd', $time);
                $num = Redis::hlen($cacheKey);
                if($num > $blackConfig['1_day_search_num']) {
                    $log['type'] = 7;
                    $log['desc'] = '1天之内搜索超过'.$blackConfig['1_day_search_num'].'次';
                    break;
                }
            }
            //1分钟之内搜索
            if(!empty($blackConfig['1_minute_search_num'])) {
                $cacheKey = $this->userBlackCounterSearchKey.$userId.':'.date('YmdHi', $time);
                $num = Redis::hlen($cacheKey);
                if($num > $blackConfig['1_minute_search_num']) {
                    $log['type'] = 8;
                    $log['desc'] = '1分钟之内搜索超过'.$blackConfig['1_minute_search_num'].'次';
                    break;
                }
            }
            //举报
            if(!empty($blackConfig['report_hour_num']) && !empty($blackConfig['report_user_num'])) {
                $reoprtUserIds = [];
                for($i=0;$i<$blackConfig['report_hour_num'];$i++) {
                    $cacheKey = $this->userBlackCounterReportKey.$userId.':'.date('YmdH', ($time-3600*$i));
                    $userIds = Redis::SMEMBERS($cacheKey);
                    if(!empty($userIds)) {
                        $reoprtUserIds = array_unique(array_merge($reoprtUserIds, $userIds));
                    }
                }
                if(count($reoprtUserIds) >= $blackConfig['report_user_num']) {
                    $log['type'] = 9;
                    $log['desc'] = '被多个用户举报';
                    break;
                }
            }
            //语言
            if(!empty($blackConfig['black_hour_num']) && !empty($blackConfig['black_word_num'])) {
                $wordLogIds = [];
                for($i=0;$i<$blackConfig['black_hour_num'];$i++) {
                    $cacheKey = $this->userBlackCounterWordKey.$userId.':'.date('YmdH', ($time-3600*$i));
                    $logIds = Redis::SMEMBERS($cacheKey);
                    if(!empty($logIds)) {
                        $wordLogIds = array_unique(array_merge($wordLogIds, $logIds));
                    }
                }
                if(count($wordLogIds) >= $blackConfig['black_word_num']) {
                    $log['type'] = 9;
                    $log['desc'] = '私信&公屏内容包含黑名单语言';
                    break;
                }
            }

        } while (false);

        $result = 0;
        if(!empty($log)) {
            //用户是否在黑名单中
            $ifBlack = $this->getBlackListByUserId($userId);
            if($ifBlack) {
                return 1;
            }

            $log['user_id'] = $userId;
            $log['status'] = 1;
            $result = DB::table($this->table)->insertGetId($log);

            //清理缓存
            $key = $this->userBlackKey.$userId;
            Redis::DEL($key);
        }

        return $result;
    }

    /**
     * 删除黑名单
     */
    public function deleteBlacklist($userId, $reason='')
    {
        if(empty($userId)) {
            return false;
        }

        $res = DB::table($this->table)->where('user_id', $userId)->where('status', 1)->update(['status' => 0, 'reason' => $reason]);

        // 使用Redis的KEYS命令获取所有匹配的键
        $keys = Redis::Keys('USERBLACK:COUNTER:*');
        // 删除所有匹配的键
        foreach ($keys as $key) {
            Redis::del($key);
        }

        //清理缓存
        $key = $this->userBlackKey.$userId;
        Redis::DEL($key);

        return $res;
    }

    /**
     * 新增系统用户黑名单
     */
    public function blackListAdd($userId)
    {
        if(empty($userId)) {
            return false;
        }
        $info = DB::table($this->table)
            ->select("user_id")
            ->where('user_id', $userId)
            ->where("status", 1)
            ->get()->toArray();
        if(!empty($info)) {
            return false;
        }
        $log = [];
        $log['type'] = 0;
        $log['desc'] = '运营操作';
        $log['user_id'] = $userId;
        $log['status'] = 1;
        $result = DB::table($this->table)->insertGetId($log);

        //清理缓存
        $key = $this->userBlackKey.$userId;
        Redis::DEL($key);

        return $result;
    }

    /**
     * 新增用户黑名单
     */
    public function blackListPromptlyAdd($userId, $desc, $type)
    {
        if(empty($userId)) {
            return false;
        }
        $info = DB::table($this->table)
            ->select("user_id")
            ->where('user_id', $userId)
            ->where("status", 1)
            ->get()->toArray();
        if(!empty($info)) {
            return false;
        }
        $log = [];
        $log['type'] = $type;
        $log['desc'] = $desc;
        $log['user_id'] = $userId;
        $log['status'] = 1;
        $result = DB::table($this->table)->insertGetId($log);

        //清理缓存
        $key = $this->userBlackKey.$userId;
        Redis::DEL($key);

        return $result;
    }

    //添加黑名单语言
    public function addBlackWord($data)
    {
        $id = DB::table($this->blackWordTable)->insertGetId($data);

        $cacheKey = $this->blackWordAllKey.'1';
        Redis::del($cacheKey);

        $cacheKey = $this->blackWordAllKey.'2';
        Redis::del($cacheKey);

        return $id;
    }

    //编辑黑名单语言
    public function editBlackWord($id, $params)
    {
        $upData = [];
        if(!empty($params['word_desc'])) {
            $upData['word_desc'] = $params['word_desc'];
        }
        if(!empty($params['promptly_type'])) {
            $upData['promptly_type'] = $params['promptly_type'];
        }
        if(!empty($params['is_delete'])) {
            $upData['is_delete'] = $params['is_delete'];
        }
        if(!empty($params['admin_id'])) {
            $upData['admin_id'] = $params['admin_id'];
        }

        if(empty($upData)) {
            return 0;
        }

        $res = DB::table($this->blackWordTable)->where('id', $id)->update($upData);

        $cacheKey = $this->blackWordAllKey.'1';
        Redis::del($cacheKey);

        $cacheKey = $this->blackWordAllKey.'2';
        Redis::del($cacheKey);

        return $res;
    }

    /**
     * 获取所有黑名单语言
     */
    public function blackWordAll($promptlyType){
        $cacheKey = $this->blackWordAllKey.$promptlyType;
        $list = Redis::get($cacheKey);
        if(empty($list)){
            $list = DB::table($this->blackWordTable)->where('is_delete', 0)->where('promptly_type', $promptlyType)->select(['id','word_desc'])->get()->toArray();
            $list = self::objToArray($list);
            if(!empty($list)) {
                Redis::setex($cacheKey, 86400, json_encode($list));
            }
        }else{
            $list = json_decode($list, true);
        }

        return $list;
    }

    //添加黑名单语言用户记录
    public function addBlackWordLog($data)
    {
        $id = DB::table($this->blackWordLogTable)->insertGetId($data);

        return $id;
    }

    /**
     * 获取系统用户黑名单根据用户ID
     */
    public function getBlackListByUserId($userId)
    {
        $result = 0;
        do {
            if(empty($userId)) {
                break;
            }

            $key = $this->userBlackKey.$userId;
            $res = Redis::get($key);//1=是 2=否
            if(empty($res)) {
                $info = DB::table($this->table)
                    ->select("user_id")
                    ->where('user_id', $userId)
                    ->where("status", 1)
                    ->first();
                $info = objToArray($info);
                if(empty($info)) {
                    Redis::SETNX($key, 2);
                    $result = 0;
                }else{
                    Redis::SETNX($key, 1);
                    $result = 1;
                }
            }else{
                $result = $res==1 ? 1 : 0;
            }

        } while (false);

        return $result;
    }


}
